/*
指针数组：
        本质上是一个数组，存储多个指针类型元素的数组
        定义：
            数据类型  *数组名[常量表达式]；
            int *p_num[4];//表示可以指向4个不同的int类型的地址   可以看作是4个指针变量
            int num[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};//二维数组
            在二维数组中num+i:就是num[i]的首地址 ， num[i]可以看作是一个一维数组，
            那么num[i]+j 就是&num[ i][j],而num[i]就是*(num+i)  因此
                *(num+i)+j======= &num[i][j]
                *(*(num+i)j)====== num[i][j]
数组指针：
        本质上是一个指针，是一个行指针
        定义:
            数据类型（*指针变量名)[常量表达式];
            int (*p_num)[4];//表示的是可以指向一个含4个元素的一维数组
            int num[3][4];
            p_num=num; / /可以将p_num 当作是num使用  表示当前p_num指向了num的整个第0行
            在这里 p_num是可以进行自增运算的 p_num++; 指向了下一行数据
多级指针：
        二维指针：指向指针的指针
        三维指针
常见问题：
        *p++;*(p++)等价于先使用*p然后p++
        *++p;*(++p)等价于先p++,然后使用*p
        (*p)++先使用*p然后执行*p的值+1
        ++*p先执行*p的值+1，然后再使用*p
主函数的参数
    int main(int argc,char *argv[]);
    argc:命令的条数
    argv:字符类型指针数组 ，可以存多条字符串 ，其实是用来存多条命令
    主函数参数：可以方便与用户/终端进行交互  ，主函数是不能去调用的，

函数指针
    函数类型   （*函数指针变量名）（参数类型）；
    int (*fun_p)(int a,int b);//函数指针
    上述函数指针 只能指向返回值为int类型，形式参数为两个int类型的函数
字符串处理函数
    strncpy：strncpy(s1,s2,6);//把s2的前6个复制到s1中
    strncat：strncat(s1,s2,5);//把s2的前5个拼接在s1后
    strncmp：strncmp(s1,s2,5);//判断s1和s2的前五个是否相等
回调函数
    概念：函数实现方 不方便调用该函数，而由接口提供方来调用该函数，就称为回调函数
    回调函数通常用于处理事件、执行异步操作或响应用户输入等场景。
    回调函数的实现：
        回调函数可以通过函数指针来实现
        用函数指针作为一个函数参数去传递
*/

#include <stdio.h>
#include <string.h>
void test(void)
{
    int num[3]={1,2,3};//整型数组
    int a=10,b=20,c=30;
    int *p_num[3]={&a,&b,&c};//指针数组  每一个元素存的地址
    //p_num[0] 指向了a的地址    也就是说*(p_num[0])就是a
    //在p_num这个数组中  p_num+i:&p_num[i]  因此 *(p_num+i)就是p_num[i]，那么*(*(p_num+i))就是a
    printf("a=%d\n",a);
    printf("*p_num[0]:%d\n",*p_num[0]);
    printf("&p_num[0]:%p,p_num+0:%p\n",&p_num[0],p_num+0);//指针数组p_num的首地址
    printf("p_num[0]:%p,*(p_num+0):%p,&a=%p\n",p_num[0],*(p_num+0),&a);//p_num[0]的值
    printf("*(*p_num+0):%d\n",*(*(p_num+0)));
    int i;
    for(i=0;i<3;i++)
    {
        printf("%d\t",*(*(p_num+i)));
    }
}
//指针数组
void test2(void)
{
    int num[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};//二维数组
    int *p_num[3]={NULL};//指针数组
    int i;
    //分别让p_num每一个元素指向二维数组的每一行的首地址
    for(i=0;i<3;i++)
    {
        p_num[i]=num[i];
    }
    //通过指针数组遍历二维数组
    for(i=0;i<3;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%d\t",*(*(p_num+i)+j));
        }
        printf("\n");
    }
}
//数组指针
void test3(void)
{
    int num[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};//二维数组
    int (*p)[4];//数组指针与二维数组
    p=num;//p指向的二维数组的整个第0行
    //第一种
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<4;j++)
        {
            printf("%d\t",*(*(p+i)+j));
        }
        printf("\n");
    }
    //第二种
    for(int i=0;i<3;i++,p++)//p++ 指向下一行
    {
        for(int j=0;j<4;j++)
        {
            printf("%d\t",*(*(p)+j));
        }
        printf("\n");
    }
}
//多级指针
void test4(void)
{
    int a=10;
    int *p=&a;//一级指针
    int **q=&p;//二级指针
    int ***r=&q;//三级指针
    printf("a=%d\n",a);
    printf("*p=%d\n",*p);
    printf("**q=%d\n",**q);
    printf("***r=%d\n",***r);
}

int getsum(int a,int b)
{
    return a+b;
}
int getcha(int a,int b)
{
    return a-b;
}
//主函数的参数
// int main(int argc,char *argv[])
// {
//     int i;
//     int a,b;
//     //test4();
//     //while(1);
//     for(i=0;i<argc;i++)
//     {
//         printf("%s\n",argv[i]);
//     }
//     a=atoi(argv[1]);
//     b=atoi(argv[2]);
//     int sum=a+b;
//     printf("sum=%d\n",sum);

//     printf("函数指针\n");
//     int (*p_fun)(int,int);//函数指针
//     p_fun=getsum;//函数指针指向  函数的首地址  函数名就是函数的首地址
//     int res;//结果
//     res=(*p_fun)(10,20);//第一种
//     printf("res=%d\n",res);
//     p_fun=getcha;
//     res=p_fun(10,20);
//     printf("res=%d\n",res);
//     return 0;
// }

void print(int n)
{
    printf("打扫%d号教室\n",n);
}
void print1(int n)
{
    printf("打扫%d号实验室\n",n);
}
void clean(int n,void(*f)(int))
{
    f(n);
}
int main(void)
{
    //回调函数
    clean(3,print);
    clean(5,print1);
    printf("\n");
    //字符串处理函数
    char s1[20]={"hello world"},s2[20]={"HELLO world"};
    strncpy(s1,s2,6);//把s2的前6个复制到s1中
    printf("s1:%s\n",s1);
    strncat(s1,s2,5);//把s2的前5个拼接在s1后
    printf("s1:%s\n",s1);
    strncpy(s1,"hello",5);
    printf("s1:%s\n",s1);
    if(strncmp(s1,s2,5)==0)//判断s1和s2的前五个是否相等
    {
        printf("前面5个字符相等");
    }
    else
    {
        printf("前面5个字符不相等");
    }
    printf("\n");
    return 0;
}